package com.oversea.service.impl;

import org.hibernate.Query;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import static com.oversea.util.ParamUtil.*;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import com.oversea.service.CommonService;
import com.oversea.util.searchcontext.SearchCondition;
import com.oversea.util.searchcontext.SearchContext;
import com.oversea.util.searchcontext.SearchOption;

public class CommonServiceImpl<T> extends HibernateDaoSupport implements
		CommonService<T> {

	private Class<T> clazz;

	@SuppressWarnings("unchecked")
	public CommonServiceImpl() {
		this.clazz = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
		System.out.println("----------------------------" + clazz.getName());
	}

	public T save(T t) {
		getSession().save(t);
		return t;
	}

	public void delete(T t) {
		getSession().delete(t);
	}

	public void deleteById(int objId) {
		T t = getObjById(objId);
		delete(t);
	}

	public void update(T t) {
		getSession().update(t);
	}

	@SuppressWarnings("unchecked")
	public T getObjById(int objId) {
		return (T) getSession().get(clazz, objId);
	}

	@SuppressWarnings("unchecked")
	public List<T> getObjectTotalList(SearchContext searchContext){
		StringBuffer queryStr = new StringBuffer();
		queryStr.append("select t from ").append(
				searchContext.getSearchClass().getName()).append(" as t ");
		List<Object> args = new ArrayList<Object>();
		StringBuffer where = new StringBuffer();
		getWhereHql(searchContext, args, where);
		queryStr.append(where);
		
		String orderBy = "desc";
		if (isNotEmpty(searchContext.getOrderBy())) {
			orderBy = searchContext.getOrderBy();
		}
		String orderByField = "id";
		if (isNotEmpty(searchContext.getOrderByField())) {
			orderByField = searchContext.getOrderByField();
		}
		queryStr.append(" order by t.");
		queryStr.append(orderByField);
		queryStr.append(" ");
		queryStr.append(orderBy);
		
		Query query = getSession().createQuery(queryStr.toString());
		for (int i = 0; i < args.size(); i++) {
			query.setParameter(i, args.get(i));
		}
		System.out.println("count query:>>> " + queryStr.toString());
		return query.list();
	}
	
	public Long getObjectCount(SearchContext searchContext) {
		StringBuffer queryStr = new StringBuffer();
		queryStr.append("select count(id) from ").append(
				searchContext.getSearchClass().getName()).append(" as t ");
		List<Object> args = new ArrayList<Object>();
		StringBuffer where = new StringBuffer();
		getWhereHql(searchContext, args, where);
		queryStr.append(where);
		Query query = getSession().createQuery(queryStr.toString());
		for (int i = 0; i < args.size(); i++) {
			query.setParameter(i, args.get(i));
		}
		System.out.println("count query:>>> " + queryStr.toString());
		return (Long) query.uniqueResult();
	}

	@SuppressWarnings("unchecked")
	public List<T> getObjectList(SearchContext searchContext, int pageSize,
			int pageNumber) {
		StringBuffer queryStr = new StringBuffer();
		queryStr.append("select t from ").append(
				searchContext.getSearchClass().getName()).append(" as t ");
		List<Object> args = new ArrayList<Object>();
		StringBuffer where = new StringBuffer();
		getWhereHql(searchContext, args, where);
		queryStr.append(where);
		
		String orderBy = "desc";
		if (isNotEmpty(searchContext.getOrderBy())) {
			orderBy = searchContext.getOrderBy();
		}
		String orderByField = "id";
		if (isNotEmpty(searchContext.getOrderByField())) {
			orderByField = searchContext.getOrderByField();
		}
		queryStr.append(" order by t.");
		queryStr.append(orderByField);
		queryStr.append(" ");
		queryStr.append(orderBy);
		
		Query query = getSession().createQuery(queryStr.toString());
		for (int i = 0; i < args.size(); i++) {
			query.setParameter(i, args.get(i));
		}
		query.setFirstResult(pageSize * (pageNumber > 1 ? pageNumber - 1 : 0));
		query.setMaxResults(pageSize);
		System.out.println("count query:>>> " + queryStr.toString());
		return query.list();
	}

	@SuppressWarnings("unchecked")
	public void getWhereHql(SearchContext searchContext, List args,
			StringBuffer where) {

		int ll = searchContext.getSearchContextSize();
		int l = searchContext.getSearchOptionSize();
		if ((l > 0 || ll > 0)) {
			if (where.length() <= 0) {
				where.append(" where");
			} else {
				if (!where.toString().endsWith("where")) {
					where.append(getAndOrBySearchConditon(searchContext
							.getCondition()));
				}
			}
		}

		if (l > 0) {

			// 处理不在searchcontext里的searchoption
			if (where.toString().trim().endsWith(")")) {
				where.append(" and ");
			}
			where.append("(");
			StringBuffer where1 = new StringBuffer();

			for (int i = 0; i < l; i++) {
				SearchOption searchOption = searchContext.getSearchOption(i);
				getHqlBySearchOption(args, where1, searchOption);
			}
			where.append(where1);
			where.append(")");
		}

		if (ll > 0) {
			for (int i = 0; i < ll; i++) {
				SearchContext context = searchContext.getSearchContext(i);
				getWhereHql(context, args, where);
			}
		}
	}

	public String getAndOrBySearchConditon(SearchCondition.Condition condition) {
		String str = "";
		switch (condition) {
		case and:
			str = " and ";
			break;
		case or:
			str = " or ";
			break;
		}
		return str;
	}

	@SuppressWarnings("unchecked")
	public void getHqlBySearchOption(List args, StringBuffer where,
			SearchOption searchOption) {
		// andOrWhere(where, searchOption.getCondition());
		if (where.length() > 0) {
			where.append(getAndOrBySearchConditon(searchOption.getCondition()));
		}
		where.append(" t.").append(searchOption.getFieldName());

		if (!isNotEmpty(searchOption.getFieldName2())) {
			switch (searchOption.getOption()) {
			case eqaul:
				where.append(" = ? ");
				break;
			case noteqaul:
				where.append(" != ? ");
				break;
			case in:
				where.append(" in(" + searchOption.getValue() + ") ");
				break;
			case like:
				where.append(" like ? ");
				break;
			case bigthan:
				where.append(" > ? ");
				break;
			case smallthan:
				where.append(" < ? ");
				break;
			case bigthanandequal:
				where.append(" >= ? ");
				break;
			case smallthanandeqaul:
				where.append(" <= ? ");
				break;
			case isnull:
				where.append(" is null ");
				break;
			case isnotnull:
				where.append(" is not null ");
				break;
			}

			if (searchOption.getOption() != SearchOption.Option.in
					&& searchOption.getOption() != SearchOption.Option.isnotnull
					&& searchOption.getOption() != SearchOption.Option.isnull) {
				args.add(searchOption.getValue());
			}
		} else {
			switch (searchOption.getOption()) {
			case eqaul:
				where.append(" = ");
				break;
			case noteqaul:
				where.append(" != ");
				break;
			case bigthan:
				where.append(" >  ");
				break;
			case smallthan:
				where.append(" < ");
				break;
			case bigthanandequal:
				where.append(" >= ");
				break;
			case smallthanandeqaul:
				where.append(" <= ");
				break;
			}
			where.append(" t.").append(searchOption.getFieldName2());
		}
	}

}
